<template><div><h1 id="js-的防抖与节流" tabindex="-1"><a class="header-anchor" href="#js-的防抖与节流" aria-hidden="true">#</a> JS 的防抖与节流</h1>
<p>在前端开发过程中会遇到一些高频事件，比如 input 输入事件、页面滚动事件、视窗大小变化事件等等，这些都是频繁触发的事件。有些时候在这些事件被触发时会调用后端接口，为了降低后端服务器的压力和代码的执行频率，就要用到 JS 的防抖与节流了。</p>
<!--  -->
<h2 id="防抖" tabindex="-1"><a class="header-anchor" href="#防抖" aria-hidden="true">#</a> 防抖</h2>
<h3 id="什么是防抖" tabindex="-1"><a class="header-anchor" href="#什么是防抖" aria-hidden="true">#</a> 什么是防抖？</h3>
<p>防抖就是指当用户频繁触发某个操作时，如果在指定的时间内再次触发该操作，那么就清除前面触发的操作，直到用户操作之后的指定时间内不再操作，我们再处理这个事件。简单来说就是多次触发同一个事件，只执行最后一次。只执行一次。</p>
<h3 id="代码" tabindex="-1"><a class="header-anchor" href="#代码" aria-hidden="true">#</a> 代码</h3>
<div class="language-javascript line-numbers-mode" data-ext="js"><pre v-pre class="language-javascript"><code><span class="token doc-comment comment">/**
 * <span class="token keyword">@method</span> debounce  防抖函数
 * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">{</span>Function<span class="token punctuation">}</span></span> <span class="token parameter">callBack</span> 防抖结束后执行的代码块
 * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">{</span>Number<span class="token punctuation">}</span></span> <span class="token parameter">wait</span> 设定防抖的时间
 * <span class="token keyword">@return</span> <span class="token class-name"><span class="token punctuation">{</span>Function<span class="token punctuation">}</span></span> 返回一个防抖功能函数
 */</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">debounce</span><span class="token punctuation">(</span><span class="token parameter">callBack<span class="token punctuation">,</span> wait</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 定义一个变量存储setTimeout的index</span>
	<span class="token keyword">var</span> timer<span class="token punctuation">;</span>

	<span class="token comment">// 返回一个具有防抖功能的函数</span>
	<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 每次调用函数前把之前的 setTimeout 清除掉</span>
		<span class="token function">clearTimeout</span><span class="token punctuation">(</span>timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token comment">// 获取参数</span>
		<span class="token keyword">var</span> agrs <span class="token operator">=</span> arguments<span class="token punctuation">;</span>
		<span class="token comment">// 创建新的 setTimeout</span>
		timer <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
			<span class="token comment">// 传入参数</span>
			<span class="token function">callBack</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> agrs<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span><span class="token punctuation">,</span> wait<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="节流" tabindex="-1"><a class="header-anchor" href="#节流" aria-hidden="true">#</a> 节流</h2>
<h3 id="什么是节流" tabindex="-1"><a class="header-anchor" href="#什么是节流" aria-hidden="true">#</a> 什么是节流？</h3>
<p>节流就是指当用户在指定的时间内频繁触发某个操作时，只执行第一次或者最后一次用户的操作，并且是周期性的执行。简单来说就是在一定时间内多次触发同一个事件，只执行第一次或者最后一次。可以执行多次。</p>
<h3 id="代码-1" tabindex="-1"><a class="header-anchor" href="#代码-1" aria-hidden="true">#</a> 代码</h3>
<div class="language-javascript line-numbers-mode" data-ext="js"><pre v-pre class="language-javascript"><code><span class="token doc-comment comment">/**
 * <span class="token keyword">@method</span> debounce  防抖函数
 * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">{</span>Function<span class="token punctuation">}</span></span> <span class="token parameter">callBack</span> 防抖结束后执行的代码块
 * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">{</span>Number<span class="token punctuation">}</span></span> <span class="token parameter">wait</span> 设定防抖的时间
 * <span class="token keyword">@param</span> <span class="token class-name"><span class="token punctuation">{</span>Boolean<span class="token punctuation">}</span></span> <span class="token parameter">immediate</span> 是否立即执行
 * <span class="token keyword">@return</span> <span class="token class-name"><span class="token punctuation">{</span>Function<span class="token punctuation">}</span></span> 返回一个防抖功能函数
 */</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">throttle</span><span class="token punctuation">(</span><span class="token parameter">callBack<span class="token punctuation">,</span> wait<span class="token punctuation">,</span> immediate</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 如果immediate没有传值，默认为true，即：立即执行</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>immediate <span class="token operator">===</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		immediate <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// 判断是否立即执行</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>immediate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 立即执行使用时间戳的方式</span>
		<span class="token comment">// 定义一个变量，保存上一次执行时的执行</span>
		<span class="token keyword">var</span> lastTime<span class="token punctuation">;</span>

		<span class="token comment">// 返回一个具有节流功能的函数</span>
		<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 如果是第一次或者当前时间与上一次的执行的事件间隔大于需要等待的时间时执行</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>lastTime <span class="token operator">||</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> lastTime <span class="token operator">>=</span> wait<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token comment">// 传入参数</span>
				<span class="token function">callBack</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
				<span class="token comment">// 当前操作已执行，获取当前执行的时间作为上一次执行的时间</span>
				lastTime <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取当前时间戳</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
		<span class="token comment">// 不需要立即执行使用时间戳的方式</span>
		<span class="token comment">// 定义一个变量保存 setTimeout 的 index</span>
		<span class="token keyword">var</span> timer<span class="token punctuation">;</span>
		<span class="token comment">// 返回一个具有防抖功能的函数</span>
		<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 判断是否已经存在 setTimeout</span>
			<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>timer<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token comment">// 如果不存在 就添加一个 setTimeout 等待wait时间过后执行callBack</span>
				<span class="token comment">// 定义一个变量保存传过来的参数</span>
				<span class="token keyword">var</span> agrs <span class="token operator">=</span> arguments<span class="token punctuation">;</span>
				<span class="token comment">// 添加 setTimeout</span>
				timer <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
					<span class="token comment">// 传入参数</span>
					<span class="token function">callBack</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> agrs<span class="token punctuation">)</span><span class="token punctuation">;</span>

					<span class="token comment">// 操作已执行，清除延时器</span>
					<span class="token function">clearTimeout</span><span class="token punctuation">(</span>timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token comment">// 将timer赋值为null</span>
					timer <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
				<span class="token punctuation">}</span><span class="token punctuation">,</span> wait<span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token comment">// 如果存在 setTimeout 就等待 setTimeout 执行</span>
		<span class="token punctuation">}</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="防抖与节流的区别" tabindex="-1"><a class="header-anchor" href="#防抖与节流的区别" aria-hidden="true">#</a> 防抖与节流的区别</h2>
<p><strong>时间限定</strong>：</p>
<ul>
<li><strong>防抖</strong>：用户连续多次点击，只执行一次。</li>
<li><strong>节流</strong>：用户连续多次点击，在一定时间内只执行一次</li>
</ul>
</div></template>


